package ssen.mvc.ondisplay {
import flash.display.DisplayObjectContainer;
import flash.events.Event;

import ssen.mvc.base.CommandMap;
import ssen.mvc.base.Context;
import ssen.mvc.base.ContextDispatcher;
import ssen.mvc.base.SwiftSuspendersInjector;
import ssen.mvc.core.ICommandMap;
import ssen.mvc.core.IContext;
import ssen.mvc.core.IContextDispatcher;
import ssen.mvc.core.IContextView;
import ssen.mvc.core.IContextViewInjector;
import ssen.mvc.core.IInjector;
import ssen.mvc.core.IViewCatcher;
import ssen.mvc.core.IViewCreator;
import ssen.mvc.core.IViewInjector;

public class DisplayContext extends Context {
	private var _dispatcher:IContextDispatcher;
	private var _injector:IInjector;
	private var _viewCatcher:IViewCatcher;
	private var _viewCreator:IViewCreator;
	private var _viewInjector:IViewInjector;
	private var _contextViewInjector:IContextViewInjector;
	private var _commandMap:ICommandMap;

	public function DisplayContext(contextView:IContextView, parentContext:IContext=null) {
		super(contextView, parentContext);
	}

	//=========================================================
	// initialize
	//=========================================================
	final override protected function initialize():void {
		super.initialize();

		var contextView:DisplayObjectContainer=this.contextView as DisplayObjectContainer;

		// stage 가 있으면 바로 start, 아니면 added to stage 까지 지연시킴
		if (contextView.stage) {
			startupContextView();
		} else {
			contextView.addEventListener(Event.ADDED_TO_STAGE, addedToStage);
		}
	}

	//==========================================================================================
	// dispose resources
	//==========================================================================================
	override protected function dispose():void {
		super.dispose();

		_dispatcher=null;
		_injector=null;
		_viewCatcher=null;
		_viewCreator=null;
		_viewInjector=null;
		_contextViewInjector=null;
	}

	//=========================================================
	// initialize context
	//=========================================================
	private function startupContextView():void {
		if (viewInjector.hasMapping(contextView)) {
			viewInjector.injectInto(contextView);
		}

		startup();

		contextView.addEventListener(Event.REMOVED_FROM_STAGE, removedFromStage);
	}

	private function addedToStage(event:Event):void {
		contextView.removeEventListener(Event.ADDED_TO_STAGE, addedToStage);
		startupContextView();
	}

	private function removedFromStage(event:Event):void {
		contextView.removeEventListener(Event.REMOVED_FROM_STAGE, removedFromStage);
		shutdown();
		dispose();
	}

	//=========================================================
	// implementation getters
	//=========================================================
	final override public function get dispatcher():IContextDispatcher {
		if (_dispatcher) {
			return _dispatcher;
		}

		_dispatcher=parentContext === null ? new ContextDispatcher : new ContextDispatcher(parentContext.dispatcher);

		return _dispatcher;
	}

	final override public function get injector():IInjector {
		if (_injector) {
			return _injector;
		}

		_injector=parentContext === null ? new SwiftSuspendersInjector : parentContext.injector.createChild();

		return _injector;
	}

	final override protected function get viewCatcher():IViewCatcher {
		return _viewCatcher||=new DisplayViewCatcher(viewInjector, contextViewInjector, contextView);
	}

	final override protected function get viewCreator():IViewCreator {
		return _viewCreator||=new DisplayViewCreator(viewInjector, contextViewInjector);
	}

	final override protected function get viewInjector():IViewInjector {
		return _viewInjector||=new DisplayViewInjector(injector);
	}

	final override protected function get contextViewInjector():IContextViewInjector {
		return _contextViewInjector||=new DisplayContextViewInjector(this);
	}

	final override public function get commandMap():ICommandMap {
		return _commandMap||=new CommandMap(dispatcher.eventDispatcher, injector);
	}
}
}
